package jp.ac.nitech.matlab.najm.server;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import jp.ac.nitech.matlab.najm.io.LiveTrace;
import jp.ac.nitech.matlab.najm.io.TraceFactory;
import jp.ac.nitech.matlab.najm.net.Packet;
import jp.ac.nitech.matlab.najm.net.Protocol;



/**
 * <[  بسم الله الرحمان الرحيم  ]
 * @author k-hon
 * SNodeHandler, handles the real data operations with clients
 * 		
 * Rules:
 * 	
 */
public class SNodeHandler implements Runnable {

	private static final int BUFFER_SIZE = 131072;
	
	private byte[] buffer;

	int size;
	int ID;
	Socket socket;
	LiveTrace trace = (LiveTrace)TraceFactory.getTrace();
	
	public SNodeHandler(int id, Socket sock) {
		this.ID = id;
		trace.info(this, ID, " new thread");
		socket = sock;
	}
	
	public void run(){
		int i=0;
		int j = 0;
		try {
				InputStream input = socket.getInputStream();
				OutputStream output = socket.getOutputStream();
				Packet p = new Packet(Packet.CTRL);
				input.read(p.getBuffer());
				String cmd = p.getCtrlCmd(); String target = p.getCtrlTarget();
				trace.info(this, ID, " ["+cmd+target+"]");
				if(cmd.compareTo(Protocol.REQ_GET)==0){
					put(output, target);
				}
				else if(cmd.compareTo(Protocol.REQ_PUT)==0){
					get(input, target);
				}
				if(cmd.compareTo("FIN")==0) i=1; //exit .. send fin msg?
			//}
			this.fin();
		} catch (Exception e) {
			e.printStackTrace();
			i = -1;
		}
	}
	//termination code
	private void fin()throws Exception{
		trace.info(this, ID, " Req.FIN <= client...\nClosing");
		this.socket.close();
	}
	
	//get from client
	private void get(InputStream input, String target) {
		try{
			buffer = new byte[BUFFER_SIZE];
			System.out.println(" client <====data=| ");
			int i = 0; int j=0;
			long t1 = System.currentTimeMillis();
			while((i=input.read())>-1){
				buffer[j] = (byte)i;
				//System.out.print(buffer[j]);
				j++;
			}
			long t2 = System.currentTimeMillis();
			double rate = 1000*j/(t2-t1);
			trace.info(this, ID, " transfer time: "+(t2-t1)+" for "+j+" bytes, hence "+rate+" B/s");
			trace.info(this, ID, " client <=data====| ");
			String docRoot = SSetting.getInstance().getSetting("documentRoot");
			FileOutputStream fos = new FileOutputStream(new File(docRoot + target));
			trace.info(this, ID, " |=write===>  "+target);
			fos.write(buffer, 0, j);
			fos.close();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	//send to client
  private void put(OutputStream output, String target) {
	  int i;
		String docRoot = SSetting.getInstance().getSetting("documentRoot");
		System.out.println("docroot is "+docRoot);
		try{
			FileInputStream fis = new FileInputStream(docRoot+target);
			byte[] buffer = new byte[BUFFER_SIZE];
			i = fis.read(buffer);		
			trace.info(this, ID, " =data====> client");
			for (int j = 0; j < i; j++) {
				output.write(buffer[j]);
				//System.out.print(buffer[j]);
			}
			trace.info(this, ID, " ====data=> client");
			output.flush();
			output.close();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}